<?php

class ProductSearch {
	
	private $query;
	
	private $filter = array();
	
	private $category_id;
	
	private $order;
	
	public $filters = array();
	
	/**
	 * Zend_Db object
	 *
	 * @var object
	 * @access private
	 **/
	private $db;
	
	public function __construct() {
		global $db;
		$this->db = $db;
	}
	
	public function query($query) {
		$this->query = $query;
	}
	
	public function filter($abbr, $value) {
		$this->filter[$abbr] = $value;
	}
	
	public function category($category_id) {
		$this->category_id = $category_id;
	}
	
	public function order($order) {
		$this->order = $order;
	}
	
	public function results($offset, $show) {
		global $site;
		$sql = 'SELECT SQL_CALC_FOUND_ROWS p.id';
		if ($this->query) $sql .= $this->db->quoteInto(', MATCH(title, description, short_description, categories) AGAINST (?) AS score', $this->query);
		$sql .= $this->db->quoteInto(' FROM shop_products p LEFT JOIN shop_categories_products cp ON cp.product_id=p.id WHERE parent_id IS NULL AND active=1 AND deleted=0 AND site_id=?', $site['id']);
		if ($this->query) {
			$terms = explode(' ', $this->query);
			foreach($terms as $term) {
				$sql .= $this->db->quoteInto(" AND CONCAT_WS(' ', title, description, short_description, categories) LIKE ?", '%' . $term . '%');
			}
		}
		if ($this->category_id) $sql .= $this->db->quoteInto(' AND category_id=?', $this->category_id);
		
		foreach($this->filter as $key => $value) {
			if ($attribute_id = $this->db->fetchOne("SELECT id FROM shop_products_attributes WHERE filter=?", $key)) {
				$sql .= $this->db->quoteInto(" AND id IN (SELECT DISTINCT p.parent_id FROM shop_products_attributes_values pav LEFT JOIN shop_products p ON pav.product_id=p.id WHERE attribute_id={$attribute_id} AND value=?)", $value);
			} else if ($simpleattribute_id = $this->db->fetchOne("SELECT id FROM shop_products_simpleattributes WHERE filter=?", $key)) {
				$sql .= $this->db->quoteInto(" AND id IN (SELECT DISTINCT COALESCE(p.parent_id, p.id) FROM shop_products_simpleattributes_values psv LEFT JOIN shop_products p ON psv.product_id=p.id WHERE simpleattribute_id={$simpleattribute_id} AND value=?)", $value);
			} else if ($meta_id = $this->db->fetchOne("SELECT id FROM shop_products_metas WHERE filter=?", $key)) {
				$sql .= $this->db->quoteInto(" AND id IN (SELECT DISTINCT COALESCE(p.parent_id, p.id) FROM shop_products_metas_values pmv LEFT JOIN shop_products p ON pmv.product_id=p.id WHERE meta_id={$meta_id} AND value=?)", $value);
			}
		}
		
		$sql .= ' GROUP BY p.id';
		
		if (!$this->order and $this->query) {
			$sql .= " HAVING score ORDER BY score DESC";
		}
		
		$sql .= " LIMIT {$offset}, {$show}";
		
		// echo $sql;
		
		$products = $this->db->fetchAll($sql);
		
		$this->totalResults = $this->db->fetchOne('SELECT FOUND_ROWS()');
		
		$product_ids = array(0);
		foreach($products as $i => $product) {
			$product_ids[] = $product['id'];
			$object = new Product($product['id'], false);
			$products[$i] = array_merge($object->export(), array('score' => (isset($product['score']) ? $product['score'] : null)));
		}
		
		if ($this->order) {
			usort($products, array('ProductSearch', 'order_' . $this->order));
		}
		
		$product_ids = join(',', $product_ids);
		
		$filters1 = $this->db->fetchAll("SELECT id, title, filter FROM shop_products_attributes WHERE filter IS NOT NULL");
		foreach($filters1 as $i => $filter) {
			$filters1[$i]['values'] = $this->db->fetchCol("SELECT DISTINCT value FROM shop_products_attributes_values WHERE attribute_id=? AND (product_id IN ({$product_ids}) OR product_id IN (SELECT id FROM shop_products WHERE parent_id IN ({$product_ids}))) ORDER BY sort", $filter['id']);
			if (!count($filters1[$i]['values'])) unset($filters1[$i]);
		}
		$filters2 = $this->db->fetchAll("SELECT id, title, filter FROM shop_products_simpleattributes WHERE filter IS NOT NULL");
		foreach($filters2 as $i => $filter) {
			$filters2[$i]['values'] = $this->db->fetchCol("SELECT DISTINCT value FROM shop_products_simpleattributes_values WHERE simpleattribute_id=? AND (product_id IN ({$product_ids}) OR product_id IN (SELECT id FROM shop_products WHERE parent_id IN ({$product_ids}))) ORDER BY sort", $filter['id']);
			if (!count($filters2[$i]['values'])) unset($filters2[$i]);
		}
		$filters3 = $this->db->fetchAll("SELECT id, title, filter FROM shop_products_metas WHERE filter IS NOT NULL");
		foreach($filters3 as $i => $filter) {
			$filters3[$i]['values'] = $this->db->fetchCol("SELECT DISTINCT value FROM shop_products_metas_values WHERE meta_id=? AND (product_id IN ({$product_ids}) OR product_id IN (SELECT id FROM shop_products WHERE parent_id IN ({$product_ids}))) ORDER BY sort", $filter['id']);
			if (!count($filters3[$i]['values'])) unset($filters3[$i]);
		}
		
		$this->filters = array_merge($filters1, $filters2, $filters3);
		
		return $products;
	}
	
	public function totalResults() {
		return $this->totalResults;
	}
	
	
	private function order_alphabetical($a, $b)   { return strcasecmp($a['title'], $b['title']);               }
	private function order_popular($a, $b)        { return strcmp($b['purchase_count'], $a['purchase_count']); }
	private function order_newest($a, $b)         { return strcmp($b['timestamp'], $a['timestamp']);           }
	private function order_price_high_low($a, $b) { return numcmp($b['price'], $a['price']);                   }
	private function order_price_low_high($a, $b) { return numcmp($a['price'], $b['price']);                   }


}